多 Agent 并发开发指南(同一台电脑)

通用开发规范。适用:同一台电脑上多个 opencode 实例 / 多个会话同时开发同一个仓库。

1. 结论先行

2. 文件修改机制(为什么"改不同行"大多没事)

3. 隔离方案对比

方案 隔离度 成本 说明
git worktree(推荐) 文件级完全隔离 低 同一 .git,多工作目录,各自分支
完全 clone 最彻底 高 独立 .git,同步/推送更麻烦
同目录多分支 ❌ 不可行 — HEAD/工作区共享,互相覆盖

4. 通用执行步骤

4.1 提交基线

cd <repo-root>
git status
git add -A && git commit -m "chore: snapshot before worktree concurrency"
# 或:git stash(stash 列表在同仓库各 worktree 间共享,可在新 worktree 里 apply)

4.2 创建 worktree

cd <repo-root>
git worktree add -b feat/agentA ../<repo>-agentA
git worktree add -b feat/agentB ../<repo>-agentB
git worktree list

4.3 初始化每个 worktree

4.4 并发工作约定

4.5 收尾

cd <repo-root>
# 分支合并回 main 后
git worktree remove ../<repo>-agentA
git worktree prune

5. 通用隔离点清单(并发前逐项检查)

类别 需要隔离的东西 做法
进程停止 按路径子串 pkill -f "<项目/子目录>" 会跨 worktree 误杀 改 PID 文件 kill,兜底用 worktree 绝对路径匹配
端口 后端 / 前端 / 调试端口硬编码 端口改读环境变量,各 worktree 分配不同端口
服务发现 前端 proxy target、服务间调用地址硬编码 跟随端口用环境变量透传
配置 .env、密钥等被 gitignore,新 worktree 不存在 手动拷贝
依赖 node_modules / .venv 随目录独立 每个 worktree 各自安装
数据 SQLite / 本地缓存文件 随 worktree 目录天然隔离
日志 相对路径日志目录 worktree 内独立,通常无碍
全局缓存 pnpm store / uv cache 等 共享只读,一般安全

6. 端口分配参考

实例 后端 前端
主目录 8000 5175
Agent A 8100 5275
Agent B 8200 5375

启动前各自 export 对应端口环境变量。

7. 风险

8. 案例:超级量化(capital markets)

8.1 仓库前提

8.2 已核实的隔离点

冲突点 位置 现状 后果
进程停止 KA04-构建/dev.sh:20-30 pkill -f "capital markets/KA04-构建/..." 路径子串匹配 worktree 路径含同样子串,任一 worktree 执行 ./dev.sh stop 会杀掉所有 worktree 的进程
后端端口 KA04-构建/dev.sh:15;实际在 backend/engine/config.py:55 api_port=8000 硬编码 两个 worktree 抢 8000
前端端口 KA04-构建/frontend/vite.config.ts port: 5175 硬编码 + strictPort: true 两个 worktree 抢 5175,启动失败
前端代理 同上 proxy target 硬编码 127.0.0.1:8000 后端换端口后代理失效
.env KA04-构建/backend/.env 被 gitignore 新 worktree 缺配置

现成能力:backend/engine/config.py:7 env_prefix="",故 api_port 可用环境变量 API_PORT 覆盖,无需改后端代码。

8.3 拟改动(待执行)

KA04-构建/dev.sh:端口环境变量化并透传;进程停止改 PID 文件 + worktree 绝对路径兜底。

BACKEND_PORT="${BACKEND_PORT:-8000}"
FRONTEND_PORT="${FRONTEND_PORT:-5175}"

# 后端:透传 API_PORT(config.py 读 API_PORT)
( cd "$ROOT/backend" && API_PORT="$BACKEND_PORT" nohup uv run python -m engine.main \
    >"$LOGS_DIR/backend.log" 2>&1 </dev/null & echo $! >"$LOGS_DIR/backend.pid" )

# 前端:端口 + 代理目标一起透传
( cd "$ROOT/frontend" && VITE_PORT="$FRONTEND_PORT" VITE_API_PORT="$BACKEND_PORT" \
    env -u http_proxy -u https_proxy -u all_proxy -u HTTP_PROXY -u HTTPS_PROXY -u ALL_PROXY \
    nohup pnpm dev >"$LOGS_DIR/frontend.log" 2>&1 </dev/null & echo $! >"$LOGS_DIR/frontend.pid" )

# stop_all:优先按 PID 文件 kill 进程组;兜底用本 worktree 绝对路径($ROOT),不再用 "capital markets/" 子串

KA04-构建/frontend/vite.config.ts:

const apiPort = process.env.VITE_API_PORT ?? '8000'

server: {
  host: '127.0.0.1',
  port: Number(process.env.VITE_PORT ?? 5175),
  strictPort: true,
  proxy: {
    '/api': { target: `http://127.0.0.1:${apiPort}`, changeOrigin: true },
    '/ws':  { target: `ws://127.0.0.1:${apiPort}`, ws: true },
  },
}

8.4 执行清单